/**
 * @(#)SmsMonitorServiceImpl.java 2017年2月14日
 * Copyright(C) 2017 ZHEXIN IT CO.,LTD. All rights reserved.
 */
package org.jsbd.boss.monitor.service;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.math.NumberUtils;
import org.jsbd.boss.common.monitor.MonitorContentTemplate;
import org.jsbd.boss.dao.impl.SimulatorActionLogDAOImpl;
import org.jsbd.boss.domian.channel.ChannelApkConfig;
import org.jsbd.boss.domian.monitor.MonitorSimulatorActionInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * 文件上传成功率监控类
 *
 * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
 * @version 1.0.0
 */
@Service("monitorSimulatorActionService")
public class MonitorSimulatorActionServiceImpl extends MonitorBaseService {
    public static final Logger LOGGER = LoggerFactory.getLogger(MonitorSimulatorActionServiceImpl.class);

    private static final DecimalFormat RATE_FORMAT = new DecimalFormat("#0.0000");

    @Autowired
    private SimulatorActionLogDAOImpl simulatorActionLogDao;

    public Map<String, String> getMonitorContent(List<ChannelApkConfig> apkList, Map<String, ChannelApkConfig> apkConfigMap, Map<String, Object> conditionMap) {

        Map<String, String> resultMap = null;
        try {
            resultMap = getMonitorContentList(apkConfigMap, conditionMap);
        } catch (Exception e) {
            resultMap = productExceptionMap(e, "文件上传成功率获取失败");
        }

        return resultMap;
//		 return getMonitorResultMap(resultList,MonitorContentTemplate.ACTION_TABLE_HEADER,"SIMULATOR_ACTION_MONITOR");
    }

    /**
     * 获取监控数据列表
     *
     * @param apkConfigMap：用于填充apkname与channelname
     * @return
     * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
     */
    public Map<String, String> getMonitorContentList(Map<String, ChannelApkConfig> apkConfigMap,
                                                     Map<String, Object> conditionMap) {

        List<Map<String, Object>> logList = simulatorActionLogDao.getSimulatorActionLogList(conditionMap);
        if (logList == null || logList.isEmpty()) {
            LOGGER.warn("getSimulatorActionLogList is null");
            return new HashMap<String, String>();
        }

        //结果列表
        List<MonitorSimulatorActionInfo> taskInfoList = new ArrayList<MonitorSimulatorActionInfo>();

        List<MonitorSimulatorActionInfo> failList = new ArrayList<MonitorSimulatorActionInfo>();

        MonitorSimulatorActionInfo allTotalInfo = new MonitorSimulatorActionInfo();
        allTotalInfo.setMark("all");
        allTotalInfo.setApkName("平均");

        long totalNum = 0;
        long successNum = 0;
        long failNum = 0;
        for (Map<String, Object> dataMap : logList) {
            String mark = (String) dataMap.get("mark");
            Long succ = (Long) dataMap.get("succ");
            Long fail = (Long) dataMap.get("fail");
            BigDecimal failRate = (BigDecimal) dataMap.get("failRate");
            Long psucc = (Long) dataMap.get("psucc");
            BigDecimal psuccRate = (BigDecimal) dataMap.get("psuccRate");

            MonitorSimulatorActionInfo info = new MonitorSimulatorActionInfo();
            info.setMark(mark);
            info.setTotalNum(succ);
            info.setSuccessNum(psucc);
            info.setFileFailNum(fail);
            if (failRate == null) {
                info.setFileFailRate(0D);
            } else {
                info.setFileFailRate(failRate.doubleValue());
            }
            if (psuccRate == null) {
                info.setSuccessRate("0");
            } else {
                info.setSuccessRate(psuccRate.toString());
            }

            ChannelApkConfig config = apkConfigMap.get(mark);
            if (config != null) {
                info.setApkName(config.getApkName());
                info.setChannelName(config.getChannelName());
            }

            successNum += info.getSuccessNum() == null ? 0 : info.getSuccessNum();
            failNum += info.getFileFailNum() == null ? 0 : info.getFileFailNum();
            totalNum += info.getTotalNum() == null ? 0 : info.getTotalNum();

            if (info.getFileFailRate() > 0) {
                failList.add(info);
            }
            taskInfoList.add(info);
        }

        //获取总平均值
        allTotalInfo.setTotalNum(totalNum);
        allTotalInfo.setSuccessNum(successNum);
        allTotalInfo.setFileFailNum(failNum);
        if (allTotalInfo.getTotalNum() == 0) {
            allTotalInfo.setFileFailRate(0.00);
            allTotalInfo.setSuccessRate("0.00");
        } else {
            allTotalInfo.setFileFailRate(allTotalInfo.getFileFailNum() * 1.0 / allTotalInfo.getTotalNum());
            allTotalInfo.setSuccessRate(RATE_FORMAT.format(allTotalInfo.getSuccessNum() * 1.0 / allTotalInfo.getTotalNum()));
        }

        Collections.sort(failList, new ActionComparator());
        Collections.sort(taskInfoList, new ActionComparator());

        taskInfoList.add(0, allTotalInfo);
        failList.add(0, allTotalInfo);

        validateOk(failList, allTotalInfo);

        //生成邮件附件
        String attachment = productEmailAttachment(MonitorContentTemplate.ACTION_TABLE_HEADER, "SIMULATOR_ACTION_MONITOR", taskInfoList);
        //生产邮件内容
        String emailContent = productEmailContent(failList, MonitorContentTemplate.ACTION_TABLE_HEADER);

        Map<String, String> resultMap = new HashMap<String, String>();
        resultMap.put("content", emailContent);
        resultMap.put("attachFile", attachment);
        resultMap.put("sheetName", "文件上传失败率监控");

        return resultMap;
    }

    /**
     * 失败率大于均值+0.01或大于0.04
     *
     * @param taskList
     * @param compareTaskInfo
     * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
     */
    public void validateOk(List<MonitorSimulatorActionInfo> taskList, MonitorSimulatorActionInfo compareTaskInfo) {
        Map<String, String> configMap = getMonitorConfig();
        String itemValue = configMap.get("file_upload_fail");

        double limit = 0;
        if (NumberUtils.isNumber(itemValue)) {
            limit = Double.valueOf(itemValue);
        }

        double failRate = Double.valueOf(compareTaskInfo.getFileFailRate()) + 0.02;
        //取小的一个
        if (limit < failRate) {
            failRate = limit;
        }
        for (MonitorSimulatorActionInfo mobileInfo : taskList) {
            double recordRate = Double.valueOf(mobileInfo.getFileFailRate());
            if (recordRate >= failRate) {
                mobileInfo.setColour("red");
            }
        }

    }

    @Deprecated
    public Map<String, Map<String, Long>> wrapDataToMap(List<Map<String, Object>> logList) {
        Map<String, Map<String, Long>> resultMap = new HashMap<String, Map<String, Long>>();
        for (Map<String, Object> logMap : logList) {
            String type = (String) logMap.get("type");
            Map<String, Long> totalMap = resultMap.get("all");
            if (totalMap == null) {
                totalMap = new HashMap<String, Long>();
                resultMap.put("all", totalMap);

            }
            Long total = totalMap.get(type);
            if (total == null) {
                total = 0L;
            }

            String mark = (String) logMap.get("mark");
            Map<String, Long> markMap = resultMap.get(mark);
            if (markMap == null) {
                markMap = new HashMap<String, Long>();
                resultMap.put(mark, markMap);
            }

            Long makrNum = markMap.get(type);
            if (makrNum == null) {
                makrNum = 0L;
            }

            Long num = (Long) logMap.get("num");
            if (num == null) {
                num = 0L;
            }

            totalMap.put(type, total + num);
            markMap.put(type, makrNum + num);
        }
        return resultMap;
    }


    public String productEmailContent(List<MonitorSimulatorActionInfo> contentInfoList) {
        return MonitorContentTemplate.getHtmlTableInfo(contentInfoList, MonitorContentTemplate.ACTION_TABLE_HEADER);
    }

    /**
     * 根据map参数组装成MonitorSimulatorActionInfo 对象
     *
     * @param mark
     * @param dataMap
     * @return
     * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
     */
    @Deprecated
    public MonitorSimulatorActionInfo getActionInfo(String mark, Map<String, Long> dataMap, ChannelApkConfig config) {
        MonitorSimulatorActionInfo taskInfo = new MonitorSimulatorActionInfo();

        Long totalTaskNum = dataMap.get("getTaskSuccess") == null ? 0L : dataMap.get("getTaskSuccess");
        Long successNum = dataMap.get("uploadSuccess") == null ? 0L : dataMap.get("uploadSuccess");
        Long fileFailNum = dataMap.get("uploadFileFail") == null ? 0L : dataMap.get("uploadFileFail");

        taskInfo.setMark(mark);
        taskInfo.setTotalNum(totalTaskNum);
        taskInfo.setFileFailNum(fileFailNum);
        taskInfo.setSuccessNum(successNum);

        if (taskInfo.getTotalNum() == 0) {
            taskInfo.setFileFailRate(0.0000);
            taskInfo.setSuccessRate("0");
        } else {
            taskInfo.setFileFailRate(taskInfo.getFileFailNum() * 1.0 / taskInfo.getTotalNum());
            taskInfo.setSuccessRate(RATE_FORMAT.format(taskInfo.getSuccessNum() * 1.0 / taskInfo.getTotalNum()));
        }

        if (config == null) {
            taskInfo.setApkName("");
            taskInfo.setChannelName("");
        } else {
            taskInfo.setApkName(config.getApkName());
            taskInfo.setChannelName(config.getChannelName());
        }
        return taskInfo;
    }

    static class ActionComparator implements Comparator<MonitorSimulatorActionInfo> {
        @Override
        public int compare(MonitorSimulatorActionInfo arg0, MonitorSimulatorActionInfo arg1) {

            Double data1 = Double.valueOf(arg1.getFileFailRate());
            Double data0 = Double.valueOf(arg0.getFileFailRate());

            if (data1 - data0 == 0) {
                return 0;
            }

            if (data1 - data0 > 0) {
                return 1;
            } else {
                return -1;
            }
        }
    }

}
